Skip to content

[TLE] barrier & wgmma pipeline with user promising support in hopper - #707

Merged
zhzhcookie merged 26 commits into
flagos-ai:triton_v3.6.xfrom
Kafka-Hatsune:tle-wgmma-user-promise
Jul 7, 2026
Merged

[TLE] barrier & wgmma pipeline with user promising support in hopper#707
zhzhcookie merged 26 commits into
flagos-ai:triton_v3.6.xfrom
Kafka-Hatsune:tle-wgmma-user-promise

Conversation

@Kafka-Hatsune

@Kafka-Hatsune Kafka-Hatsune commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

FlagTree 前端支持

通过使用tle.barrier,tle.wgmma,tle.wgmma_wait等新增API,并基于已有tle.gpu.warp_specialize API在FlagTree Triton中实现Hopper架构上的自定义复杂流水排布。具体样例参考commit tle_hopper_fa_ws_pipelined_pingpong_persistent.py实现hopper版sdpa样例。

API修改总览:

新增 barrier API:

  • tle.gpu.alloc_barriers(...)
  • tle.gpu.alloc_barrier(...)
  • tle.gpu.barrier_wait(bar, phaseIdx=None)
  • tle.gpu.barrier_arrive(bar, arrive_count=1, phaseIdx=None)
  • tle.gpu.PENDING
  • tle.gpu.READY
  • tle.gpu.barrier
  • tle.gpu.barrier_type

新增 WGMMA API:

  • tle.gpu.wgmma(...)
  • tle.gpu.wgmma_wait(pendings, acc=None)

已有 API 扩展:

  • tle.gpu.copy(...) 新增 barrier 参数,用于 TMA global-to-shared load 的显式 completion barrier。

Warp Specialization使用说明

使用 tle.gpu.warp_specialize API 时,需要把 producer / consumer partition 拆成独立的 @triton.jit 函数,并在 kernel 内用显式列表声明调用关系。

API 形式

tle.gpu.warp_specialize(
    functions_and_args,
    worker_num_warps,
    worker_num_regs,
)

参数:

  • functions_and_args:partition 列表。每一项必须是 (fn, args),其中 fn@triton.jit 函数,args 必须是 tuple。
  • functions_and_args[0]:default partition,通常作为 producer。它使用 kernel launch 的 num_warps
  • functions_and_args[1:]:worker partitions,通常作为 consumer / MMA partitions。
  • worker_num_warps:每个 worker partition 的 warp 数,长度必须等于 len(functions_and_args) - 1
  • worker_num_regs:每个 worker partition 的 requested registers,长度必须等于 len(functions_and_args) - 1

使用约定:

  • functions_and_args[0] 是 default partition,通常放 producer body。

  • functions_and_args[1:] 是 worker partitions,通常放 consumer / MMA body;如果需要多个 consumer,就重复添加多个 worker entry。

  • 多个 consumer 需要区分行为时,可以显式传入 constexpr 参数,例如 CID

  • worker function 的参数可以捕获 shared-memory buffer、barrier、descriptor、标量 constexpr 等。多个 worker 捕获同一个值时,前端会去重并作为 ttg.warp_specialize 的 partition operand 传入。

  • 使用以下 API 会启用 TLE user-promise pipeline mode:

    • tle.gpu.alloc_barriers
    • tle.gpu.alloc_barrier
    • tle.gpu.wgmma_wait

    该 mode 下:

    • 使用 mlir::triton::gpu::detail::scheduleTleWgmmaUserPromisePipeline 处理 WGMMA user-promise pipeline,并为 WGMMA 补齐 ttng::WarpGroupDotCommitOp
    • 如果这个标记在 tle.gpu.warp_specialize 调用前已经产生,则当前 warp_specialize 会 inline 展开 functions_and_args;否则保持 tt.call 调用形式。

如果需要在 worker partition 中显式使用 barrier,应在 tle.gpu.warp_specialize 前分配 barrier,并把它作为 functions_and_args 的参数传给 producer / consumer。

  empty = tle.gpu.alloc_barrier(arrive_count=2, init=tle.gpu.READY)
  tle.gpu.warp_specialize(
      [
          (producer, (...,)),
          (consumer, (empty, 0)),
          (consumer, (empty, 1)),
      ],
      [4, 4],
      [168, 168],
  )

该样例表示重复添加两个 consumer entry,让同一段 consumer body 生成两个 worker partition。每个 worker 都使用 num_warps=4requested registers=168

用户可以在函数参数中传入 constexpr 值如 01 作为 CID 区分两个 consumer worker。上面的 empty 是 mbarrier 示例;如果要做 consumer warpgroup 之间的 ping-pong 同步,参考后面的 named barrier 示例。

Barrier 相关 API

API 参数简介

本节只说明参数含义。arrive_countphaseIdx 的具体配置方式见后面的使用示例。

tle.gpu.alloc_barriers(...)

tle.gpu.alloc_barriers(
    num_barriers,
    arrive_count=1,
    init=tle.gpu.PENDING,
    expect_bytes=None,
) -> tle.gpu.barrier

参数:

  • num_barriers:tle.gpu.alloc_barriers返回一个barrier数组,此处为分配的 barrier slot 数量,必须是编译期正整数。
  • arrive_count:barrier 的计数参数,即 pending arrival count。必须是编译期正整数。mbarrier 和 named barrier 后端对它的解释不同。具体参考使用示例。
  • init:barrier初始状态,支持 tle.gpu.PENDINGtle.gpu.READY
  • expect_bytes:TMA completion barrier 期望完成的字节数。为 None 或编译期正整数。

返回值:tle.gpu.barrier,表示 barrier 数组或 barrier slot。数组通过 bars[i] 取 slot。

tle.gpu.alloc_barrier(...)

tle.gpu.alloc_barrier(
    arrive_count=1,
    init=tle.gpu.PENDING,
    expect_bytes=None,
) -> tle.gpu.barrier

返回值:单个 tle.gpu.barrier slot。它是 alloc_barriers(num_barriers=1, ...) 的语法糖。

tle.gpu.barrier_wait(...)

tle.gpu.barrier_wait(bar, phaseIdx=None) -> None

参数:

  • bar:要等待的 barrier slot,类型为 tle.gpu.barrier
  • phaseIdx:mbarrier logical use id。传入时使用 mbarrier 路径;为 None 时使用 named barrier 路径。

tle.gpu.barrier_arrive(...)

tle.gpu.barrier_arrive(bar, arrive_count=1, phaseIdx=None) -> None

参数:

  • bar:要 arrive 的 barrier slot,类型为 tle.gpu.barrier

  • arrive_count:本次 arrive 的计数权重。

    • 只用于 mbarrier 路径,表示逻辑arrive数量;
    • named barrier 路径下必须保持默认值 1。named barrier 的总参与线程数已经由 allocation 的 arrive_count 表达。
  • phaseIdx:mbarrier logical use id,第几次使用这个 slot。传入时使用 mbarrier 路径;为 None 时使用 named barrier 路径。

tle.gpu.PENDING

tle.gpu.PENDING

含义:barrier 初始不可通过。常用于 full barrier、TMA completion barrier、named barrier。

tle.gpu.READY

tle.gpu.READY

含义:barrier 初始可通过。常用于 empty barrier。READY barrier 只能走 mbarrier 路径。

tle.gpu.barrier

含义:alloc_barrier(s) 返回的 barrier value 类型。支持 bars[i] 取数组 slot。

tle.gpu.barrier_type

含义:tle.gpu.barrier 对应的类型描述。普通 kernel 代码通常不需要直接构造。

修改tle.gpu.copy(..., barrier=...)

tle.gpu.copy(src, dst, shape, offsets=None, barrier=None)

参数:

  • src:copy 源。使用 barrier 时必须是 TMA TensorDescriptor。
  • dst:copy 目标。使用 barrier 时必须是 shared-memory tle.gpu.buffered_tensor
  • shape:copy tile 的形状。
  • offsets:TMA descriptor 坐标偏移。
  • barrier:可选 completion barrier。必须来自 tle.gpu.alloc_barrier(s)(expect_bytes=...)

使用示例

mbarrier 使用路径

传入 phaseIdx 时,barrier_wait / barrier_arrive 会选择 mbarrier 路径。tle.gpu.copy(..., barrier=...) 的 TMA completion barrier 也必须走 mbarrier 路径,并且后续 wait 必须传 phaseIdx

  • 适用场景:

    • producer/consumer Empty-Full 同步。
    • TMA global-to-shared load completion。
    • init=tle.gpu.READY 的 empty barrier。
    • 需要用 logical use id 表达同一 slot 多次复用的 ping-pong / 多 stage pipeline。
  • phaseIdx 要求:

    • phaseIdx 是同一个 barrier slot 的 logical use id,也就是这个 slot 第几次被使用。它的设计意图是让循环里的同一组 barrier slot 可以被反复复用,并通过循环计数区分第几轮复用。
    • 当前实现会在内部把 logical use id 转成硬件 mbarrier phase:
      • constexpr 整数路径:(phaseIdx & 1) ^ init_polarity
      • 动态 tensor 路径:先做 phaseIdx & 1,再根据 init 调整初始 polarity
    • 用户通常传“该 slot 的复用次数”,不需要手写 & 1
    • 同一次 logical use 对应的 wait/arrive 两侧必须传入一致的 phaseIdx
    • 在 ring buffer / 多 stage pipeline 中,常见写法是 slot = iter % NUM_BUFFERSphaseIdx = iter // NUM_BUFFERS,因为同一个 slot 每隔 NUM_BUFFERS 次迭代才复用一次。
    bars = tle.gpu.alloc_barriers(
        num_barriers=NUM_BUFFERS,
        arrive_count=1,
        init=tle.gpu.READY,
    )
    
    for k_iter in range(0, NUM_ITERS):
        slot = k_iter % NUM_BUFFERS
        use_id = k_iter // NUM_BUFFERS
    
        tle.gpu.barrier_wait(bars[slot], phaseIdx=use_id)
        # ... 第 use_id 次使用 bars[slot] 对应的 shared-memory slot ...
        tle.gpu.barrier_arrive(bars[slot], phaseIdx=use_id)
  • arrive_count 配置示例:

    • 一个 consumer 到达同一个 slot 一次:

      @triton.jit
      def consumer(empty):
          use_id: tl.constexpr = 0
          tle.gpu.barrier_arrive(empty, phaseIdx=use_id)
      
      
      empty = tle.gpu.alloc_barrier(arrive_count=1, init=tle.gpu.READY)
      
      tle.gpu.warp_specialize(
          [
              (producer, (...,)),
              (consumer, (empty,)),
          ],
          [4],
          [168],
      )
    • 两个 worker consumers 共同释放同一个 slot,此时同一个 slot 会收到两次 arrive,所以 arrive_count=2

      @triton.jit
      def consumer(empty):
          use_id: tl.constexpr = 0
          # 两个 worker 都执行这里,各 arrive 1 次。
          tle.gpu.barrier_arrive(empty, phaseIdx=use_id)
      
      
      empty = tle.gpu.alloc_barrier(arrive_count=2, init=tle.gpu.READY)
      
      tle.gpu.warp_specialize(
          [
              (producer, (...,)),
              (consumer, (empty,)),
              (consumer, (empty,)),
          ],
          [4, 4],
          [168, 168],
      )
    • 两个 worker consumers 使用各自独立 slot:传入barrier slots array,通过CID区分自己需要使用的slot。

      @triton.jit
      def consumer(empty, CID: tl.constexpr):
          use_id: tl.constexpr = 0
          tle.gpu.barrier_arrive(empty[CID], phaseIdx=use_id)
      
      
      empty = tle.gpu.alloc_barriers(num_barriers=2, arrive_count=1, init=tle.gpu.READY)
      
      tle.gpu.warp_specialize(
          [
              (producer, (...,)),
              (consumer, (empty, 0)),
              (consumer, (empty, 1)),
          ],
          [4, 4],
          [168, 168],
      )
  • 其他注意事项:

    • 后端选择:

      • 同一个 barrier slot 不能混用 mbarrier 和 named barrier 路径。
      • barrier_wait / barrier_arrive 只要传入 phaseIdx,当前 slot 就会记录为 mbarrier backend。
    • 初始状态:

      • init=tle.gpu.READY 只适合 mbarrier 路径。
      • 如果 READY barrier 不传 phaseIdx,会选择 named barrier 路径并报错。
    • TMA completion:

      • expect_bytes barrier 只能用于 TMA global-to-shared completion。
      • 使用 expect_bytes 的 barrier 必须通过 tle.gpu.copy(..., barrier=...) 触发 completion,并且必须用 phaseIdx 等待。

named barrier 使用路径

不传 phaseIdx 时,barrier_wait / barrier_arrive 会选择 named barrier 路径。

  • 适用场景:

    • 不需要 TMA completion 的 CTA-scope rendezvous。
    • consumer 内部或多个 consumer warp group 之间的轻量同步。
    • 同步点可以用静态 barrier slot 表达,且不需要 init=READY
  • named_barrierarrive_count是参与线程数 named_num_threads ,通常写成 参与 warp 数 * 32。当前实现会把 allocation 的 arrive_count 同时传给 named arrive 和 named wait。因此,使用named_barrier只需要alloc后直接wait+arrive。举例:

  • 两个 4-warp consumer workers 通过同一个 named barrier 同步,总参与线程数是 256。这里两个 worker 复用同一段 consumer body,并通过显式传入的 CID 区分一个 worker 做 non-blocking arrive,另一个 worker 做 wait/sync;不需要在 barrier_arrive/ barrier_wait调用参数里写arrive_count

    @triton.jit
    def consumer(sync, CID: tl.constexpr):
        if CID == 0:
            tle.gpu.barrier_arrive(sync[0])
        else:
            tle.gpu.barrier_wait(sync[0])
    
    
    sync = tle.gpu.alloc_barriers(num_barriers=1, arrive_count=256)
    
    tle.gpu.warp_specialize(
        [
            (producer, (...,)),
            (consumer, (sync, 0)),
            (consumer, (sync, 1)),
        ],
        [4, 4],
        [168, 168],
    )
  • 其他注意事项:

    • named barrier 只支持 init=tle.gpu.PENDING,不支持 READY
    • named barrier 不支持 expect_bytes,因此不能用于 tle.gpu.copy(..., barrier=...) 的 TMA completion。
    • named barrier 要求静态 barrier slot index,例如 sync[0];不能用动态 slot index。

Empty-Full 同步示例

@triton.jit
def producer(a_desc, a_smem, a_empty, a_full):
    phase: tl.constexpr = 0
    tle.gpu.barrier_wait(a_empty, phaseIdx=phase)
    tle.gpu.copy(a_desc, a_smem, [BLOCK_M, BLOCK_K], [0, 0], barrier=a_full)


@triton.jit
def consumer(a_smem, a_empty, a_full):
    phase: tl.constexpr = 0
    tle.gpu.barrier_wait(a_full, phaseIdx=phase)
    # consume a_smem ...
    tle.gpu.barrier_arrive(a_empty, phaseIdx=phase)


@triton.jit
def kernel(...):
    a_empty = tle.gpu.alloc_barrier(init=tle.gpu.READY)
    a_full = tle.gpu.alloc_barrier(expect_bytes=A_TILE_BYTES)

    tle.gpu.warp_specialize(
        [
            (producer, (a_desc, a_smem, a_empty, a_full)),
            (consumer, (a_smem, a_empty, a_full)),
        ],
        [4],
        [168],
    )

copy(..., barrier=...) 只支持 TMA global-to-shared load。不支持 shared-to-global TMA store、普通 copy、named barrier 或没有 expect_bytes 的 barrier。

TMA completion 示例

TMA completion 只能使用 mbarrier 后端,通常写 arrive_count=1,因为 arrival 来自这一条 TMA copy 的 completion:

bar = tle.gpu.alloc_barrier(expect_bytes=BLOCK_M * BLOCK_K * 2)

tle.gpu.copy(
    a_desc,
    a_smem,
    [BLOCK_M, BLOCK_K],
    [pid_m * BLOCK_M, pid_k * BLOCK_K],
    barrier=bar,
)
tle.gpu.barrier_wait(bar, phaseIdx=0)

WGMMA 相关 API

API 参数简介

tle.gpu.wgmma(...)

tle.gpu.wgmma(
    a,
    b,
    acc=None,
    input_precision=None,
    max_num_imprecise_acc=None,
    out_dtype=tl.float32,
    trans_a: tl.constexpr = False,
    trans_b: tl.constexpr = False,
) -> tl.tensor

参数:

  • a:WGMMA A operand。可以是 shared-memory tle.gpu.buffered_tensor 或 register tl.tensor
  • b:WGMMA B operand。当前必须是 shared-memory tle.gpu.buffered_tensor
  • acc:输入 accumulator。为 None 时前端会生成零 accumulator。
  • input_precision:dot input precision。为 None 时使用当前 builder 默认值。
  • max_num_imprecise_acc:FP8 imprecise accumulation 控制参数,不改变返回 tensor dtype,仅在FP8 GEMM上有效。使用 FP8 -> F32 WGMMA 当前有效值需 >= 32;None 在 sm90 上默认 2^30。值越小越偏精度,越大越偏性能。
  • out_dtype:输出 accumulator dtype,默认 tl.float32。它决定结果/accumulator 的 dtype;
  • trans_a:是否转置 A operand,必须是编译期 bool。
  • trans_b:是否转置 B operand,必须是编译期 bool。

返回值:异步 WGMMA accumulator dependency value。普通 tensor op、reduce、store 消费前必须调用 tle.gpu.wgmma_wait(...)

tle.gpu.wgmma_wait(...)

tle.gpu.wgmma_wait(pendings, acc=None) -> tl.tensor

参数:

  • pendings:允许保留的 outstanding WGMMA group 数量。0 表示完全等待。
  • acc:要等待的 accumulator。若省略且第一个参数是 tensor,则等价于 tle.gpu.wgmma_wait(0, acc)

返回值:wait 后可安全消费的 accumulator tensor。

使用示例

单次 WGMMA:

a_smem = tle.gpu.alloc([64, 16], dtype=tl.float16, layout=None, scope=tle.gpu.smem)
b_smem = tle.gpu.alloc([16, 16], dtype=tl.float16, layout=None, scope=tle.gpu.smem)

acc = tle.gpu.wgmma(a_smem, b_smem, out_dtype=tl.float32)
acc = tle.gpu.wgmma_wait(0, acc)

流水中保留一个 pending group,WGMMA是warpgroup级别的FIFO队列模型:

acc1 = tle.gpu.wgmma(a0_smem, b0_smem, acc1)
acc2 = tle.gpu.wgmma(a1_smem, b1_smem, acc2)
## do something else
acc1 = tle.gpu.wgmma_wait(1, acc1) # permit acc2 is pending

当前性能

测试说明

  • vllm:0.17.0
    • 测试函数:vllm.vllm_flash_attn.flash_attn_interface.flash_attn_varlen_func
  • torch:2.11.0a0+eb65b36914.nv26.02(docker:http://nvcr.io/nvidia/pytorch:26.02-py3)
    • 测试函数:torch.nn.attention.varlen.varlen_attn
  • GPU:H800
    • NVIDIA-SMI 570.124.06
    • Driver Version: 570.124.06
    • CUDA Version: 13.1

通过FlagGems benchmark测试,右侧三列表示以vllm为100%性能,其他三个的性能比。

workload dtype vllm torch fa2 fa3_ws torch_x fa2_x fa3_ws_x
paged_decodeish_long_k_tq265_q16_k2333_h16_hk8_d128 bfloat16 0.865248 1.653744 0.749856 0.831632 0.523 1.154 1.040
paged_medium_or_prefill_tq512_q512_k512_h16_hk8_d128 bfloat16 0.019008 0.031424 0.068176 0.307984 0.605 0.279 0.062
paged_mixed_short_tq265_q61_k515_h16_hk8_d128 bfloat16 0.080928 0.142560 0.084352 0.340512 0.568 0.959 0.238
paged_short_tq72_q70_k70_h16_hk8_d128 bfloat16 0.010848 0.016832 0.067200 0.310112 0.644 0.161 0.035
decode_b16_kv1k_d128_gqa4 bfloat16 0.051968 0.060208 0.124224 0.136976 0.863 0.418 0.379
decode_b16_mixed_d128_gqa4 bfloat16 0.089376 0.092064 0.156032 0.141440 0.971 0.573 0.632
decode_b32_kv2k_d128_gqa4 bfloat16 0.123776 0.133088 0.122208 0.137792 0.930 1.013 0.898
decode_b8_kv1k_d192_gqa4 bfloat16 0.045696 0.052704 0.123792 0.136864 0.867 0.369 0.334
decode_b8_kv1k_d256_gqa4 bfloat16 0.052992 0.060896 0.123840 0.137536 0.870 0.428 0.385
paged_decode_b16_kvmix_bs16_d128_gqa4 bfloat16 0.104896 0.111008 0.163424 0.584352 0.945 0.642 0.180
paged_decode_b64_bs16_d128_gqa4 bfloat16 0.507616 0.675456 0.495824 0.748464 0.752 1.024 0.678
paged_decode_b8_bs16_d192_gqa4 bfloat16 0.058592 0.065696 0.122816 0.527776 0.892 0.477 0.111
paged_decode_b8_bs16_d256_gqa4 bfloat16 0.066688 0.073760 0.122416 0.526624 0.904 0.545 0.127
paged_serve_b32_1pf_31dec_bs16_d128_gqa4 bfloat16 0.528944 0.754176 0.701920 0.831552 0.701 0.754 0.636
paged_uniform_b4_s4k_bs16_d128_mha bfloat16 1.989568 1.806064 1.697888 4.788192 1.102 1.172 0.416
prefill_b2_s16k_d128_mha bfloat16 11.676528 12.517968 13.475936 10.867424 0.933 0.866 1.074
prefill_b4_s2k_d128_mha bfloat16 0.508848 0.549152 0.539840 0.423360 0.927 0.943 1.202
prefill_b4_s4k_d128_gqa4 bfloat16 1.632208 1.761088 1.804704 1.362816 0.927 0.904 1.198
prefill_b4_s4k_d128_mha bfloat16 1.664192 1.779824 1.865184 1.509344 0.935 0.892 1.103
prefill_b4_s8k_d128_gqa4 bfloat16 5.864672 6.411216 6.668400 5.302976 0.915 0.879 1.106
prefill_b4_s8k_d128_mha bfloat16 5.990816 6.470304 6.881216 5.588336 0.926 0.871 1.072
prefill_b8_s2k_d64_mha bfloat16 0.516192 0.559664 0.568672 0.458752 0.922 0.908 1.125
varlen_longtail_d128_gqa4 bfloat16 6.075776 6.571136 6.837792 4.982176 0.925 0.889 1.220
varlen_mixed_d128_gqa4 bfloat16 0.437632 0.476576 0.572416 0.884704 0.918 0.765 0.495
varlen_serve_b32_1pf_31dec_d128_gqa4 bfloat16 0.566752 0.617216 0.636128 1.468096 0.918 0.891 0.386
paged_decodeish_long_k_tq265_q16_k2333_h16_hk8_d128 float16 0.926128 1.705664 0.745312 0.832656 0.543 1.243 1.112
paged_medium_or_prefill_tq512_q512_k512_h16_hk8_d128 float16 0.019680 0.031584 0.067680 0.308944 0.623 0.291 0.064
paged_mixed_short_tq265_q61_k515_h16_hk8_d128 float16 0.081856 0.144336 0.084160 0.341984 0.567 0.973 0.239
paged_short_tq72_q70_k70_h16_hk8_d128 float16 0.010816 0.016992 0.067552 0.303584 0.637 0.160 0.036
decode_b16_kv1k_d128_gqa4 float16 0.052064 0.060160 0.122912 0.137408 0.865 0.424 0.379
decode_b16_mixed_d128_gqa4 float16 0.089696 0.092288 0.155872 0.138240 0.972 0.575 0.649
decode_b32_kv2k_d128_gqa4 float16 0.124768 0.133152 0.121728 0.137440 0.937 1.025 0.908
decode_b8_kv1k_d192_gqa4 float16 0.045696 0.053376 0.122992 0.137152 0.856 0.372 0.333
decode_b8_kv1k_d256_gqa4 float16 0.053056 0.061024 0.122688 0.135920 0.869 0.432 0.390
paged_decode_b16_kvmix_bs16_d128_gqa4 float16 0.105152 0.111040 0.161280 0.579504 0.947 0.652 0.181
paged_decode_b64_bs16_d128_gqa4 float16 0.509376 0.674656 0.496512 0.748112 0.755 1.026 0.681
paged_decode_b8_bs16_d192_gqa4 float16 0.058752 0.065408 0.122240 0.521968 0.898 0.481 0.113
paged_decode_b8_bs16_d256_gqa4 float16 0.067552 0.073920 0.121968 0.521104 0.914 0.554 0.130
paged_serve_b32_1pf_31dec_bs16_d128_gqa4 float16 0.543200 0.740128 0.699968 0.827104 0.734 0.776 0.657
paged_uniform_b4_s4k_bs16_d128_mha float16 2.055296 1.848432 1.738624 4.778240 1.112 1.182 0.430
prefill_b2_s16k_d128_mha float16 12.097888 12.680480 13.526624 11.175936 0.954 0.894 1.082
prefill_b4_s2k_d128_mha float16 0.518048 0.523968 0.541392 0.436080 0.989 0.957 1.188
prefill_b4_s4k_d128_gqa4 float16 1.645344 1.798016 1.824096 1.386096 0.915 0.902 1.187
prefill_b4_s4k_d128_mha float16 1.692640 1.829664 1.909344 1.565536 0.925 0.887 1.081
prefill_b4_s8k_d128_gqa4 float16 6.084064 6.541408 6.711808 5.464752 0.930 0.906 1.113
prefill_b4_s8k_d128_mha float16 6.209216 6.552352 6.945120 5.844256 0.948 0.894 1.062
prefill_b8_s2k_d64_mha float16 0.496224 0.515072 0.566784 0.458528 0.963 0.876 1.082
varlen_longtail_d128_gqa4 float16 6.262784 6.680736 6.876448 5.096096 0.937 0.911 1.229
varlen_mixed_d128_gqa4 float16 0.445216 0.479744 0.573536 0.884688 0.928 0.776 0.503
varlen_serve_b32_1pf_31dec_d128_gqa4 float16 0.561152 0.602816 0.636160 1.464928 0.931 0.882 0.383

@CLAassistant

CLAassistant commented Jun 17, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@i3wanna2
i3wanna2 marked this pull request as ready for review June 22, 2026 02:21
@i3wanna2 i3wanna2 changed the title barrier & wgmma pipeline with user promising support in hopper [TLE]barrier & wgmma pipeline with user promising support in hopper Jun 22, 2026
Comment thread include/triton/Dialect/TritonNvidiaGPU/IR/TritonNvidiaGPUOps.td
Comment thread lib/Dialect/TritonGPU/Transforms/Pipeliner/SoftwarePipeliner.cpp
@zhzhcookie

Copy link
Copy Markdown
Collaborator

Please check which newly code should be inside #ifdef __TLE__.

@Kafka-Hatsune

Kafka-Hatsune commented Jun 22, 2026

Copy link
Copy Markdown
Contributor Author

Please check which newly code should be inside #ifdef __TLE__.

fixed in commit "Guard TLE-only barrier compiler changes".

For Hopper CI fails,it seems to work fine in H800 server. What's different between my flagtree build/test command which is "pip install -e . --no-build-isolation -v"/"python3 -m pytest -s tests/test_flash_mla_sparse_fwd.py" and ci servers building and testing? I'm sure using the flagtree built triton.

image

For other CI fails,I add skipif for my new test.

please run a new round ci and I will get more information.

Comment thread python/src/gluon_ir.cc Outdated
Comment thread python/triton/compiler/code_generator.py
sunnycase

This comment was marked as outdated.

@Kafka-Hatsune
Kafka-Hatsune force-pushed the tle-wgmma-user-promise branch from b475f86 to abc69cd Compare June 26, 2026 03:42

@sunnycase sunnycase left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work on the Hopper pipeline support. One concern I have is that this introduces a separate async_task/async_tasks API for warp specialization while tle/gluon already has an existing warp_specialize API.

Could we please reuse or extend the existing warp_specialize API here instead? Having another async-task abstraction for the same concept would split the user-facing API surface and make it unclear which API users should choose. Aligning this with the existing API would keep the programming model more consistent and easier to understand.

@Kafka-Hatsune

Copy link
Copy Markdown
Contributor Author

Thanks for the work on the Hopper pipeline support. One concern I have is that this introduces a separate async_task/async_tasks API for warp specialization while tle/gluon already has an existing warp_specialize API.

Could we please reuse or extend the existing warp_specialize API here instead? Having another async-task abstraction for the same concept would split the user-facing API surface and make it unclear which API users should choose. Aligning this with the existing API would keep the programming model more consistent and easier to understand.

fixed in commit a3e7dfb. I preserve the async_task api, but now the existing warp_specialize API can be used in user_promise way to alloc/wait/arrive barrier etc.

Two notes:

  1. If you use warp_specialize API and want it to be lowered as inline, You should alloc ops using barrier api so that it will be lowered in inline way but not tt.call way before. The lower way depends on whether you use the apis which are mentioned in pipeline lower.
  2. Because here I use inline pattern, I met a problem that when I try to expand the controlflow op like forop into the new block created in ttg ws_op, there will be assert error Assertion parent && "expected valid parent region" failed. So I changed the way from creating a new block to creating a block mounted to builder's current block, then merge. For more details you can lookup the commit code.

Comment thread lib/Dialect/TritonGPU/Transforms/Pipeliner/SoftwarePipeliner.cpp
@sunnycase

Copy link
Copy Markdown
Collaborator

Thanks for the update. Since the existing warp_specialize API can now cover the user-promise use case for barrier allocation/wait/arrive, please remove the async_task/async_tasks API instead of keeping it as another user-facing abstraction.

Keeping two APIs for the same functionality would make it unclear which one users should choose, and it may give the impression that TLE does not have a unified programming model or API design. I think we should keep this centered on warp_specialize, and fold any missing capability into that API instead.

If there is still something that cannot be expressed through warp_specialize, please point it out so we can decide whether the existing API needs to be extended.

@Kafka-Hatsune

Copy link
Copy Markdown
Contributor Author

Thanks for the update. Since the existing warp_specialize API can now cover the user-promise use case for barrier allocation/wait/arrive, please remove the async_task/async_tasks API instead of keeping it as another user-facing abstraction.

Keeping two APIs for the same functionality would make it unclear which one users should choose, and it may give the impression that TLE does not have a unified programming model or API design. I think we should keep this centered on warp_specialize, and fold any missing capability into that API instead.

If there is still something that cannot be expressed through warp_specialize, please point it out so we can decide whether the existing API needs to be extended.

If there is API like tle.gpu.async_task_replica_id() regarding the following usage? It should be migrated into warp_specialize method. If there is no problem I will migrate old api tle.gpu.async_task_replica_id() in async_task into tle.gpu.warp_group_replica_id() in warp_specialize API

cid: tl.constexpr = tle.gpu.async_task_replica_id()
if cid == 1:
   tle.gpu.barrier_arrive(ping_to_c0)

@sunnycase

Copy link
Copy Markdown
Collaborator

I do not think we need to add a separate tle.gpu.warp_group_replica_id() accessor for this. The replica id can be passed explicitly through the function parameters of the warp_specialize body, for example as a tl.constexpr argument, and then used for the branch condition inside that body.

So please migrate away from async_task_replica_id(), but avoid introducing another global accessor if the id can be expressed as an explicit parameter. This keeps the warp_specialize API clearer and avoids adding another user-facing concept.

@Kafka-Hatsune

Copy link
Copy Markdown
Contributor Author

Thanks for the update. Since the existing warp_specialize API can now cover the user-promise use case for barrier allocation/wait/arrive, please remove the async_task/async_tasks API instead of keeping it as another user-facing abstraction.

Keeping two APIs for the same functionality would make it unclear which one users should choose, and it may give the impression that TLE does not have a unified programming model or API design. I think we should keep this centered on warp_specialize, and fold any missing capability into that API instead.

If there is still something that cannot be expressed through warp_specialize, please point it out so we can decide whether the existing API needs to be extended.

got it, I will remove the accessor, and replace it with function args.

@sunnycase sunnycase left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@zhzhcookie zhzhcookie changed the title [TLE]barrier & wgmma pipeline with user promising support in hopper [TLE] barrier & wgmma pipeline with user promising support in hopper Jul 7, 2026
@zhzhcookie
zhzhcookie merged commit ac594f2 into flagos-ai:triton_v3.6.x Jul 7, 2026
16 of 30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants